package edu.purdue.cs505;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class BroadcastTestNode
{
  public static void main(String[] args)
  {
    String mode = "";
    if (args.length != 3
        || !((mode = args[2]).equals("reliable") || mode.equals("fifo") || mode.equals("srb"))) {
      System.out.println("Usage: BroadcastTestNode <filename> <node id> <reliable/fifo/srb>");
      System.exit(0);
    }

    String filename = args[0];
    int myId = Integer.parseInt(args[1]) - 1;

    List<Process> processes = new ArrayList<Process>();

    InputStream fis;
    BufferedReader br;
    String line;

    try {
      fis = new FileInputStream(filename);
      br = new BufferedReader(new InputStreamReader(fis, Charset.forName("UTF-8")));
      int index = 0;
      while ((line = br.readLine()) != null) {
        String[] parts = line.split(",");
        Process p = new Process(parts[0], Integer.parseInt(parts[1]), index++);
        System.out.println(p.getIP() + ":" + p.getPort());
        processes.add(p);
      }

      // Done with the file
      br.close();
      br = null;
      fis = null;
    }
    catch (Exception e) {
      e.printStackTrace();
    }

    Process me = processes.get(myId);

    /* create this processes' reliable broadcaster */
    ReliableBroadcast bcast;
    if (mode.equals("fifo")) {
      bcast = new FIFOReliableBroadcastImpl();
      System.out.println("FIFO reliable broadcast mode started");
    }
    else if (mode.equals("srb")) {
      FIFOReliableBroadcastImpl.srbOn = true;
      FIFOReliableBroadcastImpl.deliveryDelay = 3;
      bcast = new FIFOReliableBroadcastImpl();
      System.out.println("FIFO SRB reliable broadcast mode started");
    }
    else {
      bcast = new ReliableBroadcastImpl();
      System.out.println("Reliable broadcast mode started");
    }

    bcast.init(me);
    for (Process p : processes) {
      if (p != me) {
        bcast.addProcess(p);
      }
    }
    bcast.rblisten(new PrintingReceiver());

    /* accept commands from console and run tests */
    Scanner scan = new Scanner(System.in);
    boolean acceptInput = true;
    while (acceptInput) {
      String command = scan.next();
      if (command.equals("quit") || command.equals("exit")) {
        /*
         * quit exit
         */
        bcast.halt();
        acceptInput = false;
      }
      else if (command.equals("send")) {
        /* send <contents> */
        String contents = scan.next();
        Message m = new Message();
        m.setContents(contents);
        bcast.rbroadcast(m);
      }
      else if (command.equals("spam")) {
        /* spam <num messages> */
        int count = Integer.parseInt(scan.next());
        for (int i = 1; i <= count; i++) {
          Message m = new Message();
          m.setContents("spam " + i);
          bcast.rbroadcast(m);
        }
      }
      else if (command.equals("obsspam")) {
        /* spam <num messages> <obs mod>*/
        int count = Integer.parseInt(scan.next());
        int mod = Integer.parseInt(scan.next());
        for (int i = 1; i <= count; i++) {
          Message m = new Message();
          m.setContents("obsspam " + i);
          if(i % mod == 0) {
            m.makesObsolete(i-1);
            //System.out.println(i + " makes obs " + i/mod);
          }
          bcast.rbroadcast(m);
        }

      }
    }
    scan.close();
  }
}
